package com.example.router;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcelable;
import android.util.Log;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

public final class RouterMap {

    private static final String TAG = "RouterMap";

    private static final HashMap<String,ActivityCategory> sRouterMap = new HashMap<>();

    public static void init(Context context) {
        resolveActivity(context);
    }

    @SuppressLint("WrongConstant")
    private static void resolveActivity(Context context) {
        PackageManager packageManager = context.getPackageManager();
        String packageName = context.getPackageName();
        ActivityInfo[] activityInfos;
        try {
            activityInfos = packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES).activities;
            for (ActivityInfo activityInfo : activityInfos) {
                Log.d(TAG, "resolveActivity: " + activityInfo.name);
                Class<?> aClass = Class.forName(activityInfo.name);
                if (aClass.isAnnotationPresent(ActivityRouter.class)) {
                    Log.d(TAG, "resolveActivity: path = " + aClass.getAnnotation(ActivityRouter.class).title());
                    String category = aClass.getAnnotation(ActivityRouter.class).category();
                    String title = aClass.getAnnotation(ActivityRouter.class).title();
                    String descript = aClass.getAnnotation(ActivityRouter.class).descript();
                    Class cls = aClass;
                    if (sRouterMap.get(category) == null) {
                        sRouterMap.put(category,new ActivityCategory(category));
                    }
                    sRouterMap.get(category).put(title,new RouterActivityInfo(category,title,descript,cls));
                }
            }
        } catch (PackageManager.NameNotFoundException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static ArrayList<String> getAllCategorys() {
        return new ArrayList<String>(sRouterMap.keySet());
    }

    public static ArrayList<RouterActivityInfo> getAllRouterActivityInfoByCategory(String category) {
        return sRouterMap.get(category).getAllRouterActivityInfo();
    }

    public static final class Router {

        private Bundle mBundle;
        private String mRouterAddress;
        private int mRequestCode;
        private boolean mIsRequestCode = false;
        private boolean mIsBundle = false;

        public Router setBundle(Bundle bundle) {
            this.mBundle = bundle;
            this.mIsBundle = true;
            return this;
        }

        public Router setRouterAddress(String mRouterAddress) {
            this.mRouterAddress = mRouterAddress;
            return this;
        }

        public Router setRequestCode(int requestCode) {
            this.mRequestCode = requestCode;
            this.mIsRequestCode = true;
            return this;
        }

        public void startActivity(Activity activity,RouterActivityInfo activityInfo) {
            if (mRouterAddress == null) {
                Log.d("Router", "startPath: " + mRouterAddress + " is NULL");
                return;
            }
            activityInfo.startActivity(mBundle,mIsBundle,mRequestCode,mIsRequestCode,activity);
        }

        public Router setInt(String key, Integer value) {
            checkBundle();
            mBundle.putInt(key,value);
            return this;
        }

        public Router setString(String key, String value) {
            checkBundle();
            mBundle.putString(key,value);
            return this;
        }

        private void checkBundle() {
            if (mBundle == null) {
                this.mIsBundle = true;
                mBundle = new Bundle();
            }
        }

        public Router setFloat(String key, float value) {
            checkBundle();
            mBundle.putFloat(key,value);
            return this;
        }

        public Router setBinder(String key, IBinder value) {
            checkBundle();
            mBundle.putBinder(key,value);
            return this;
        }

        public Router setIntegerArrayList(String key, ArrayList<Integer> value) {
            checkBundle();
            mBundle.putIntegerArrayList(key,value);
            return this;
        }

        public Router setStringArrayList(String key, ArrayList<String> value) {
            checkBundle();
            mBundle.putStringArrayList(key,value);
            return this;
        }

        public Router setStringArray(String key, String[] value) {
            checkBundle();
            mBundle.putStringArray(key,value);
            return this;
        }

        public Router setFloatArray(String key, float[] value) {
            checkBundle();
            mBundle.putFloatArray(key,value);
            return this;
        }

        public Router setParcelable(String key, Parcelable value) {
            checkBundle();
            mBundle.putParcelable(key,value);
            return this;
        }

        public Router setParcelableArray(String key, Parcelable[] value) {
            checkBundle();
            mBundle.putParcelableArray(key,value);
            return this;
        }

        public Router setParcelableArrayList(String key, ArrayList<Parcelable> value) {
            checkBundle();
            mBundle.putParcelableArrayList(key,value);
            return this;
        }

        public Router setBoolean(String key, boolean value) {
            checkBundle();
            mBundle.putBoolean(key,value);
            return this;
        }

        public Router setBooleanArray(String key, boolean[] value) {
            checkBundle();
            mBundle.putBooleanArray(key,value);
            return this;
        }

        public Router setSerializable(String key, Serializable value) {
            checkBundle();
            mBundle.putSerializable(key,value);
            return this;
        }

        public Router setLong(String key, long value) {
            checkBundle();
            mBundle.putLong(key,value);
            return this;
        }
    }

}
